package com.be.beadmin.system.impl.ProjectDesignServiceImpl;

import cn.hutool.core.util.ObjectUtil;
import com.be.beadmin.common.exception.BeadminException;
import com.be.beadmin.design.service.UnStandProductProcessInfoService;
import com.be.beadmin.product.entity.PlantCapacityCalendar;
import com.be.beadmin.product.repository.WorkOrderInforRepository;
import com.be.beadmin.product.service.PlantCapacityCalendarService;
import com.be.beadmin.project.dto.input.BatchPlanInfoFormDto;
import com.be.beadmin.project.entity.*;
import com.be.beadmin.project.mapper.BatchPlanMapper;
import com.be.beadmin.project.mapper.BatchPlanMapperEx;
import com.be.beadmin.project.repository.*;
import com.be.beadmin.project.service.BatchPlanService;
import com.be.beadmin.quality.entity.InspectionTask;
import com.be.beadmin.quality.entity.InspectionTemplate;
import com.be.beadmin.quality.repository.InspectionTemplateRepository;
import com.be.beadmin.quality.service.InspectionTaskService;
import com.be.beadmin.service.entity.NotifyInfo;
import com.be.beadmin.service.repository.DictTypeRepository;
import com.be.beadmin.service.repository.NotifyInfoRepository;
import com.be.beadmin.service.service.DictDataService;
import com.be.beadmin.service.service.NotifyTemplateInfoService;
import com.be.beadmin.service.service.SerialNumberService;
import com.be.beadmin.service.task.BaseTask;
import com.be.beadmin.service.task.TaskThreadPool;
import com.be.beadmin.system.service.ProductMaterialService.WorkOrderInforPmService;
import com.be.beadmin.system.service.ProjectDesignSevice.BatchPlanPdService;
import com.be.beadmin.system.service.ProjectDesignSevice.BatchProductPdService;
import com.be.beadmin.system.task.IssueWorkOrderTask;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.io.IOException;
import java.net.BindException;
import java.text.ParseException;
import java.util.*;

/**
 * @Description:
 * @author: Jiaming Zheng
 * @Date: Create in 10:25 2023/6/20
 * @Modified By:
 **/
@Service
public class BatchPlanPdServiceImpl implements BatchPlanPdService {
    @Autowired
    private BatchPlanRepository batchPlanRepository;

    @Autowired
    private TaskThreadPool taskThreadPool;

    @Autowired
    private WorkOrderInforRepository workOrderInforRepository;
    @Autowired
    private BatchProductRepository batchProductRepository;
    @Autowired
    private BatchPlanMapper batchPlanMapper;
    @Autowired
    private BatchPlanService batchPlanService;
    @Autowired
    private InspectionTemplateRepository inspectionTemplateRepository;
    @Autowired
    private InspectionTaskService inspectionTaskService;
    @Autowired
    private BatchPlanMapperEx batchPlanExMapper;
    @Autowired
    private DictTypeRepository dictTypeRepository;
    @Autowired
    private WorkOrderInforPmService workOrderInforPmService;
    @Autowired
    private DictDataService dictDataService;
    @Autowired
    private InfoRepository infoRepository;
    @Autowired
    private ProductInfoRepository productInfoRepository;
    @Autowired
    private ProductTotalInfoRepository productTotalInfoRepository ;
    @Autowired
    private BatchProductPdService batchProductPdService;
    @Autowired
    private SerialNumberService serialNumberService;

    @Autowired
    private UnStandProductProcessInfoService unStandProductProcessInfoService;

    @Autowired
    private TeamInfoRepository teamInfoRepository;

    @Autowired
    private NotifyTemplateInfoService notifyTemplateInfoService;


    @Autowired
    private PlantCapacityCalendarService plantCapacityCalendarService;
    @Autowired
    private NotifyInfoRepository notifyInfoRepository;

    @Autowired
    private PlanStageRepository planStageRepository;
    /**
     * 发布一个项目批次计划
     *
     * @param batchPlanId
     * @return
     */
    @Override
    public void issueBatchPlan(String batchPlanId) throws Exception { //下发到设计
        System.out.println("正在下发到设计");
        BatchPlan plan = batchPlanRepository.findBatchPlanByIdAndDelete(batchPlanId,0);
        if (plan == null) throw new BeadminException("未找到批次计划");
        List<BatchProduct> products = batchProductRepository.findBatchProductByBatchPlanIdAndDelete(batchPlanId,0);
        PlanStage planStage = planStageRepository.findPlanStageByPlanIdAndStageNameAndDelete(batchPlanId, "生产分料", 0);
        PlanStage planStage2 = planStageRepository.findPlanStageByPlanIdAndStageNameAndDelete(batchPlanId, "发货日期", 0);

        if (products == null) throw new BeadminException("该批次没有任何柜体");
        for (BatchProduct product : products) {
            if (product.getState() == 0) {
                product.setState(1);
                product.setBatchPlanCode(plan.getBatchPlanCode());
                // 柜体批次信息
                product.setBatchCountInfo(plan.getCurrentBatch()+"/"+plan.getBatchCount());
                // 批次交付日期
                product.setBatchDeliveryDate(planStage2.getStagePlanEndTime());
                // 设置分料计划开始时间
                product.setStageDosingStartTime(planStage.getStagePlanStartTime());
                if (product.getIsStandard()==1) {
                    product.setReviewState(2);
                }
                // 将工艺路径BOM图纸都添加到柜体上
                batchProductPdService.addFileAndBop(product);

                //  对非标准柜体的默认工艺路径，赋予默认工时0，周期0
                if (product.getIsStandard()==0){
                    unStandProductProcessInfoService.setInitialBop(product.getId(),product.getProductCode(),product.getProductType(),product.getBopCode());
                }
            }

            // 标准柜要添加BOM和图纸，以及工艺路径
        }


        batchProductRepository.saveAll(products);
        plan.setState(1);
        BatchPlan save = batchPlanRepository.save(plan);
        // 需要创建交检单
        InspectionTemplate template = inspectionTemplateRepository.findInspectionTemplateByProductTypeAndStateAndDeleteAndTypeLike("柜体","1",0,"%交检%");
        inspectionTaskService.generateSubmissionInspectionTask(save, template);

        //-------------------------------------------------------------------
        //能够成功释放
        // 项目经理 发送 项目发布 通知给  项目团队成员
        NotifyInfo notifyInfo =new NotifyInfo();
        notifyInfo.setModuleName("项目管理");
        notifyInfo.setFuncName("项目批次发布");

        String batchPlanCode = save.getBatchPlanCode();
        String infoId = save.getInfoId();
        Info info = infoRepository.findInfoByIdAndDelete(infoId,0);
        if(info == null) return ;
        String projectCode = info.getProjectCode();
        int currentBatch = save.getCurrentBatch();


        notifyInfo.setNotifyDesc("项目号["+projectCode+"],批次号["+batchPlanCode+"],第["+currentBatch+"]批次---项目批次已发放");
        notifyInfo.setNotifyType("通知");


        String teamId = info.getTeamId();
        if(teamId==null) return ;
        List<TeamInfo> teamInfoList = teamInfoRepository.findTeamInfoByTeamIdAndDelete(teamId,0);
        TeamInfo projectManager =  teamInfoRepository.findTeamInfoByTeamIdAndCategoryAndDelete(teamId,"项目经理",0);
        String senderName = "-";
        String senderId="-";
        if(projectManager!=null){
            if(projectManager.getUserName()!=null){
                senderName = projectManager.getUserName();
            }
            if(projectManager.getUserId()!=null){
                senderId = projectManager.getUserId();
            }
        }
        notifyInfo.setSenderName(senderName);
        notifyInfo.setSenderId(senderId);
        notifyInfo.setSendTime(save.getUpdateTime());
        notifyInfo = notifyInfoRepository.save(notifyInfo);

        Set<String> st =new HashSet<>();
        for (TeamInfo teamInfo:teamInfoList){
            String receiver = teamInfo.getUserName();
            if(receiver!=null&&!st.contains(receiver)){
                st.add(receiver);
                notifyTemplateInfoService.sendNotify(notifyInfo,-1,receiver,teamInfo.getUserId());
            }
        }
        //放最后
        //--------------------------------
    }

    /**
     * 批量发布项目批次计划
     *
     * @param batchPlanIds
     * @return
     */
    @Override
    public String issueBatchPlans(List<String> batchPlanIds) throws Exception, ParseException {
        int unissueCount = batchPlanRepository.countBatchPlansByStateAndIdInAndDelete(0, batchPlanIds, 0);
        if (unissueCount==0) throw new BeadminException("选中的批次都已经下发，请选择未下发的批次");
        for (String p :
                batchPlanIds) {
            BatchPlan plan = batchPlanRepository.findBatchPlanByIdAndDelete(p,0);
            if (plan == null) throw new BeadminException("未找到批次计划");
            if (plan.getState() != 0) {
                continue;
            }
            List<BatchProduct> products = batchProductRepository.findBatchProductByBatchPlanIdAndDelete(p,0);
            PlanStage planStage = planStageRepository.findPlanStageByPlanIdAndStageNameAndDelete(p, "生产分料", 0);
            PlanStage planStage2 = planStageRepository.findPlanStageByPlanIdAndStageNameAndDelete(p, "发货日期", 0);
            List<String> productIds = new ArrayList<>();
            if (products == null) throw new BeadminException("该批次没有任何柜体");

            for (BatchProduct product : products) {


                if (product.getState() == 0) {

                    // 将工艺路径BOM图纸都添加到柜体上， 这个操作很耗时，  怎么把他优化一下
                    batchProductPdService.addFileAndBop(product);



                    product.setState(1);
                    product.setBatchPlanCode(plan.getBatchPlanCode());
                    // 柜体批次信息
                    product.setBatchCountInfo(plan.getCurrentBatch()+"/"+plan.getBatchCount());
                    // 批次交付日期
                    product.setBatchDeliveryDate(planStage2.getStagePlanEndTime());
                    // 设置分料时间
                    product.setStageDosingStartTime(planStage.getStagePlanStartTime());

                    if (product.getIsStandard()==1) {
                        product.setReviewState(2);
                        productIds.add(product.getId());
                    }
                    //  对非标准柜体的默认工艺路径，赋予默认工时0，周期0
                    if (product.getIsStandard()==0){
                        unStandProductProcessInfoService.setInitialBop(product.getId(),product.getProductCode(),product.getProductType(),product.getBopCode());
                    }
                }
            }
            batchProductRepository.saveAll(products);
            plan.setState(1);
            BatchPlan save = batchPlanRepository.save(plan);


            // todo 更新该批次项目开工的实际开始日期，实际结束日期，柜体设计实际开始日期
            Date currentDate = new Date();
            PlanStage projectStart = planStageRepository.findPlanStageByPlanIdAndStageNameAndDelete(p, "项目开工",0);
            projectStart.setStageStartTime(currentDate);
            projectStart.setStageEndTime(currentDate);

            PlanStage productDesign = planStageRepository.findPlanStageByPlanIdAndStageNameAndDelete(p, "柜体设计",0);
            productDesign.setStageStartTime(currentDate);

            // todo 若该批次全为标准柜体, 由于自动审批通过需更新该批次的柜体设计实际结束日期, 物料采购实际开始日期
            boolean allStandardProduct = products.stream().allMatch(product -> product.getIsStandard() == 1);
            if (allStandardProduct){
                productDesign.setStageEndTime(currentDate);

                PlanStage materialPurchase = planStageRepository.findPlanStageByPlanIdAndStageNameAndDelete(p, "物料采购", 0);
                materialPurchase.setStageStartTime(currentDate);
                planStageRepository.save(materialPurchase);
            }
            planStageRepository.save(projectStart);
            planStageRepository.save(productDesign);

            //-------------------------------------------------------------------
            //其中某个批次，能够成功释放
            // 项目经理 发送 项目发布 通知给  项目团队成员
            NotifyInfo notifyInfo =new NotifyInfo();
            notifyInfo.setModuleName("项目管理");
            notifyInfo.setFuncName("项目批次发布");

            String batchPlanCode = save.getBatchPlanCode();
            String infoId = save.getInfoId();
            Info info = infoRepository.findInfoByIdAndDelete(infoId,0);
            if(info == null) continue ;
            String projectCode = info.getProjectCode();
            int currentBatch = save.getCurrentBatch();


            notifyInfo.setNotifyDesc("项目号["+projectCode+"], 批次号["+batchPlanCode+"], 第["+currentBatch+"]批次---项目批次已发放");
            notifyInfo.setNotifyType("通知");


            String teamId = info.getTeamId();
            if(teamId==null) continue ;
            List<TeamInfo> teamInfoList = teamInfoRepository.findTeamInfoByTeamIdAndDelete(teamId,0);
            TeamInfo projectManager =  teamInfoRepository.findTeamInfoByTeamIdAndCategoryAndDelete(teamId,"项目经理",0);
            String senderName = "-";
            String senderId="-";
            if(projectManager!=null){
                if(projectManager.getUserName()!=null){
                    senderName = projectManager.getUserName();
                }
                if(projectManager.getUserId()!=null){
                    senderId = projectManager.getUserId();
                }
            }
            notifyInfo.setSenderName(senderName);
            notifyInfo.setSenderId(senderId);
            notifyInfo.setSendTime(save.getUpdateTime());
            notifyInfo = notifyInfoRepository.save(notifyInfo);

            Set<String> st =new HashSet<>();
            for (TeamInfo teamInfo:teamInfoList){
                String receiver = teamInfo.getUserName();
                if(receiver!=null&&!st.contains(receiver)){
                    st.add(receiver);
                    notifyTemplateInfoService.sendNotify(notifyInfo,-1,receiver,teamInfo.getUserId());
                }
            }
            //--------------------------------


            // 需要创建交检单
            InspectionTemplate template = inspectionTemplateRepository.findInspectionTemplateByProductTypeAndStateAndDeleteAndTypeLike("柜体","1",0,"%交检%");
            if (template == null) {
                throw new BeadminException("未找到交检表模板");
            }
            inspectionTaskService.generateSubmissionInspectionTask(save, template);

            // 异步下发了
            // 直接下发工单
            if (!productIds.isEmpty()) {

//                IssueWorkOrderTask issueWorkOrderTask = new IssueWorkOrderTask(productIds);
//                taskThreadPool.execute(issueWorkOrderTask);
                this.taskThreadPool.execute(new BaseTask("标准柜体工单下发") {
                    @Override
                    public void doTask() {
                        try {
                            workOrderInforPmService.issueWorkOrderInforByPage(productIds);
                        } catch (ParseException e) {
                            throw new RuntimeException(e);
                        }
                    }
                });

                return "批次下发成功, 工单正在生成，柜子数量较请耐心等待";
            }


        }
        return "批次下发成功";

    }

    private void updateBatchCount(BatchPlan save) {



    }

    @Override
    @Transactional
    public void delBatchPlan(String id) {
        BatchPlan res = batchPlanRepository.findBatchPlanByIdAndDelete(id,0);
        if (res == null) {
            throw new BeadminException("数据中未找到该批次计划记录， 无法删除");
        }
        if (res.getState() !=0 ){
            throw new BeadminException("该批次计划已经下发， 无法删除");
        }

        //删除该批次
        batchProductRepository.updateBatchPlanIdByBatchPlanIdAndDelete("-1", id, 0);
        BatchPlan batchPlan = batchPlanRepository.findBatchPlanByIdAndDelete(id,0);
        batchPlan.setDelete(1);
        batchPlanRepository.save(batchPlan);

        // 更新其他批次的当前批次
       batchPlanRepository.updateBatchPlanCurrentBatch(batchPlan.getMasterPlanId(),batchPlan.getCurrentBatch());

        // 批次总数更新
        int planCount = batchPlanService.updateBatchPlanCount(batchPlan.getMasterPlanId());
        // 还需要删除批次下的所有产能
        plantCapacityCalendarService.delPlantCapacityCalendarsByBatchPlan(batchPlan);
        // 还要更新工单的这个批次总数
        workOrderInforRepository.updateBatchCountByInfoId(planCount,batchPlan.getInfoId());

        // 更新已下发批次柜体的批次信息
        batchPlanService.updateBatchProductBatchInfo(batchPlan.getMasterPlanId(),planCount, batchPlan.getCurrentBatch());

    }

    @Transactional
    @Override
    public void addBatchPlan(BatchPlanInfoFormDto batchPlaninfoDto) {

        BatchPlan batchPlan = batchPlanService.addBatchPlan(batchPlaninfoDto);

        // ------------------------------------------------------------------
        // 需要将批次总数更新到工单中
//            Integer batchCount = plan.getBatchCount();
//            updateBatchCount(save);
        workOrderInforRepository.updateBatchCountByBatchPlan(batchPlan.getId());

    }
}
